package core

import (
	"fmt"

	"github.com/ethereum/go-ethereum/params"
)

type InstructionTable [MaxOpCodesCount]*operation

//加载指令序列，写法模仿的是Geth的根据分叉加载指令集，不同点在于对于Gas的计算放到了GasSetting部分
var (
	FrontierSet = loadFrontierInstructionSet()
)

func validate(It InstructionTable) InstructionTable {
	for i, op := range It {
		if op == nil {
			panic(fmt.Sprintf("op 0x%x is not set", i))
		}
		if op.memorySize != nil && op.dynamicGas == nil {
			panic(fmt.Sprintf("op %v has dynamic memory but not dynamic gas", OpCode(i).String()))
		}
	}
	return It
}

//Frontier 版本 指令集 最初的指令
func loadFrontierInstructionSet() InstructionTable {
	table := InstructionTable{
		STOP: &operation{
			execute:     opStop,
			constantGas: 0,
			minStack:    MinStack(0, 0),
			maxStack:    MaxStack(0, 0),
			finished:    true,
		},
		ADD: &operation{
			execute:     opAdd,
			constantGas: GasFastestStep,
			minStack:    MinStack(2, 1),
			maxStack:    MaxStack(2, 1),
		},
		MUL: &operation{
			execute:     opMul,
			constantGas: GasFastStep,
			minStack:    MinStack(2, 1),
			maxStack:    MaxStack(2, 1),
		},
		SUB: &operation{
			execute:     opSub,
			constantGas: GasFastestStep,
			minStack:    MinStack(2, 1),
			maxStack:    MaxStack(2, 1),
		},
		DIV: &operation{
			execute:     opDiv,
			constantGas: GasFastStep,
			minStack:    MinStack(2, 1),
			maxStack:    MaxStack(2, 1),
		},
		SDIV: &operation{
			execute:     opSdiv,
			constantGas: GasFastStep,
			minStack:    MinStack(2, 1),
			maxStack:    MaxStack(2, 1),
		},
		MOD: &operation{
			execute:     opMod,
			constantGas: GasFastStep,
			minStack:    MinStack(2, 1),
			maxStack:    MaxStack(2, 1),
		},
		SMOD: &operation{
			execute:     opSmod,
			constantGas: GasFastStep,
			minStack:    MinStack(2, 1),
			maxStack:    MaxStack(2, 1),
		},
		ADDMOD: &operation{
			execute:     opAddmod,
			constantGas: GasMidStep,
			minStack:    MinStack(3, 1),
			maxStack:    MaxStack(3, 1),
		},
		MULMOD: &operation{
			execute:     opMulmod,
			constantGas: GasMidStep,
			minStack:    MinStack(3, 1),
			maxStack:    MaxStack(3, 1),
		},
		EXP: &operation{
			execute:    opExp,
			dynamicGas: gasExpFrontier,
			minStack:   MinStack(2, 1),
			maxStack:   MaxStack(2, 1),
		},
		SIGNEXTEND: &operation{
			execute:     opSignExtend,
			constantGas: GasFastStep,
			minStack:    MinStack(2, 1),
			maxStack:    MaxStack(2, 1),
		},
		LT: &operation{
			execute:     opLt,
			constantGas: GasFastestStep,
			minStack:    MinStack(2, 1),
			maxStack:    MaxStack(2, 1),
		},
		GT: &operation{
			execute:     opGt,
			constantGas: GasFastestStep,
			minStack:    MinStack(2, 1),
			maxStack:    MaxStack(2, 1),
		},
		SLT: &operation{
			execute:     opSlt,
			constantGas: GasFastestStep,
			minStack:    MinStack(2, 1),
			maxStack:    MaxStack(2, 1),
		},
		SGT: &operation{
			execute:     opSgt,
			constantGas: GasFastestStep,
			minStack:    MinStack(2, 1),
			maxStack:    MaxStack(2, 1),
		},
		EQ: &operation{
			execute:     opEq,
			constantGas: GasFastestStep,
			minStack:    MinStack(2, 1),
			maxStack:    MaxStack(2, 1),
		},
		ISZERO: &operation{
			execute:     opIszero,
			constantGas: GasFastestStep,
			minStack:    MinStack(1, 1),
			maxStack:    MaxStack(1, 1),
		},
		AND: &operation{
			execute:     opAnd,
			constantGas: GasFastestStep,
			minStack:    MinStack(2, 1),
			maxStack:    MaxStack(2, 1),
		},
		OR: &operation{
			execute:     opOr,
			constantGas: GasFastestStep,
			minStack:    MinStack(2, 1),
			maxStack:    MaxStack(2, 1),
		},
		XOR: &operation{
			execute:     opXor,
			constantGas: GasFastestStep,
			minStack:    MinStack(2, 1),
			maxStack:    MaxStack(2, 1),
		},
		NOT: &operation{
			execute:     opNot,
			constantGas: GasFastestStep,
			minStack:    MinStack(2, 1),
			maxStack:    MaxStack(2, 1),
		},
		BYTE: &operation{
			execute:     opByte,
			constantGas: GasFastestStep,
			minStack:    MinStack(2, 1),
			maxStack:    MaxStack(2, 1),
		},
		KECCAK256: &operation{
			execute:     opKeccak256,
			constantGas: params.Keccak256Gas, //30
			dynamicGas:  gasKeccak256,
			minStack:    MinStack(2, 1),
			maxStack:    MaxStack(2, 1),
			memorySize:  MemoryKeccak256,
		},
		ADDRESS: &operation{
			execute:     opAddress,
			constantGas: GasQuickStep,
			minStack:    MinStack(0, 1),
			maxStack:    MaxStack(0, 1),
		},
		BALANCE: &operation{
			execute:     opBalance,
			constantGas: params.BalanceGasFrontier,
			minStack:    MinStack(1, 1),
			maxStack:    MaxStack(1, 1),
		},
		ORIGIN: &operation{
			execute:     opOrigin,
			constantGas: GasQuickStep,
			minStack:    MinStack(0, 1),
			maxStack:    MaxStack(0, 1),
		},
		CALLER: &operation{
			execute:     opCaller,
			constantGas: GasQuickStep,
			minStack:    MinStack(0, 1),
			maxStack:    MaxStack(0, 1),
		},
		CALLVALUE: &operation{
			execute:     opCallValue,
			constantGas: GasQuickStep,
			minStack:    MinStack(0, 1),
			maxStack:    MaxStack(0, 1),
		},
		CALLDATALOAD: &operation{
			execute:     opCallDataLoad,
			constantGas: GasFastStep,
			minStack:    MinStack(1, 1),
			maxStack:    MaxStack(1, 1),
		},
		CALLDATASIZE: &operation{
			execute:     opCallDataSize,
			constantGas: GasQuickStep,
			minStack:    MinStack(1, 1),
			maxStack:    MaxStack(1, 1),
		},
		CALLDATACOPY: &operation{
			execute:     opCallDataCopy,
			constantGas: GasFastestStep,
			dynamicGas:  gasCallDataCopy,
			minStack:    MinStack(3, 0),
			maxStack:    MaxStack(3, 0),
		},
		CODESIZE: &operation{
			execute:     opCodeSize,
			constantGas: GasQuickStep,
			minStack:    MinStack(0, 1),
			maxStack:    MaxStack(0, 1),
		},
		CODECOPY: &operation{
			execute:     opCodeCopy,
			constantGas: GasFastestStep,
			dynamicGas:  gasCodeCopy,
			minStack:    MinStack(3, 0),
			maxStack:    MaxStack(3, 0),
			memorySize:  MemoryCodeCopy,
		},
		GASPRICE: &operation{
			execute:     opGasPrice,
			constantGas: GasQuickStep,
			minStack:    MinStack(0, 1),
			maxStack:    MaxStack(0, 1),
		},
		EXTCODESIZE: &operation{
			execute:     opExtCodeSize,
			constantGas: params.ExtcodeCopyBaseFrontier,
			minStack:    MinStack(1, 1),
			maxStack:    MaxStack(1, 1),
		},
		EXTCODECOPY: &operation{
			execute:     opExtCodeCopy,
			constantGas: params.ExtcodeCopyBaseFrontier,
			dynamicGas:  gasExtCodeCopy,
			minStack:    MinStack(4, 0),
			maxStack:    MaxStack(4, 0),
			memorySize:  MemoryExtCodeCopy,
		},
		BLOCKHASH: &operation{
			execute:     opBlockHash,
			constantGas: GasExtStep,
			minStack:    MinStack(1, 1),
			maxStack:    MaxStack(1, 1),
		},
		COINBASE: &operation{
			execute:     opCoinbase,
			constantGas: GasQuickStep,
			minStack:    MinStack(0, 1),
			maxStack:    MaxStack(0, 1),
		},
		TIMESTAMP: &operation{
			execute:     opTimeStamp,
			constantGas: GasQuickStep,
			minStack:    MinStack(0, 1),
			maxStack:    MaxStack(0, 1),
		},
		NUMBER: &operation{
			execute:     opNumber,
			constantGas: GasQuickStep,
			minStack:    MinStack(0, 1),
			maxStack:    MaxStack(0, 1),
		},
		DIFFICULTY: &operation{
			execute:     opDifficulty,
			constantGas: GasQuickStep,
			minStack:    MinStack(0, 1),
			maxStack:    MaxStack(0, 1),
		},
		POP: &operation{
			execute:     opPop,
			constantGas: GasQuickStep,
			minStack:    MinStack(1, 0),
			maxStack:    MaxStack(1, 0),
		},
		MLOAD: &operation{
			execute:     opMload,
			constantGas: GasFastestStep,
			dynamicGas:  gasMLoad,
			minStack:    MinStack(1, 1),
			maxStack:    MaxStack(1, 1),
			memorySize:  MemoryMLoad,
		},
		MSTORE: &operation{
			execute:     opMstore,
			constantGas: GasFastestStep,
			dynamicGas:  gasMStore,
			minStack:    MinStack(2, 0),
			maxStack:    MaxStack(2, 0),
			memorySize:  MemoryMStore,
		},
		MSTORE8: &operation{
			execute:     opMstore8,
			constantGas: GasFastestStep,
			dynamicGas:  gasMStore8,
			minStack:    MinStack(2, 0),
			maxStack:    MaxStack(2, 0),
			memorySize:  MemoryMStore8,
		},
		SLOAD: &operation{
			execute:     opSload,
			constantGas: params.SloadGasFrontier,
			minStack:    MinStack(1, 1),
			maxStack:    MaxStack(1, 1),
		},
		SSTORE: &operation{
			execute:    opSstore,
			dynamicGas: gasSStore,
			minStack:   MinStack(2, 0),
			maxStack:   MaxStack(2, 0),
			isWriter:   true,
		},
		JUMP: &operation{
			execute:     opJump,
			constantGas: GasMidStep,
			minStack:    MinStack(1, 0),
			maxStack:    MaxStack(1, 0),
		},
		JUMPI: &operation{
			execute:     opJumpi,
			constantGas: GasSlowStep,
			minStack:    MinStack(2, 0),
			maxStack:    MaxStack(2, 0),
		},
		PC: &operation{
			execute:     opPc,
			constantGas: GasQuickStep,
			minStack:    MinStack(0, 1),
			maxStack:    MaxStack(0, 1),
		},
		MSIZE: &operation{
			execute:     opMsize,
			constantGas: GasQuickStep,
			minStack:    MinStack(0, 1),
			maxStack:    MaxStack(0, 1),
		},
		GAS: &operation{
			execute:     opGas,
			constantGas: GasQuickStep,
			minStack:    MinStack(0, 1),
			maxStack:    MaxStack(0, 1),
		},
		JUMPDEST: &operation{
			execute:     opJumpdest,
			constantGas: params.JumpdestGas,
			minStack:    MinStack(0, 0),
			maxStack:    MaxStack(0, 0),
		},
		PUSH1: &operation{
			execute:     opPush1,
			constantGas: GasFastestStep,
			minStack:    MinStack(0, 1),
			maxStack:    MaxStack(0, 1),
		},
		PUSH2: &operation{
			execute:     makePush(2, 2),
			constantGas: GasFastestStep,
			minStack:    MinStack(0, 1),
			maxStack:    MaxStack(0, 1),
		},
		PUSH3: &operation{
			execute:     makePush(3, 3),
			constantGas: GasFastestStep,
			minStack:    MinStack(0, 1),
			maxStack:    MaxStack(0, 1),
		},
		PUSH4: &operation{
			execute:     makePush(4, 4),
			constantGas: GasFastestStep,
			minStack:    MinStack(0, 1),
			maxStack:    MaxStack(0, 1),
		},
		PUSH5: &operation{
			execute:     makePush(5, 5),
			constantGas: GasFastestStep,
			minStack:    MinStack(0, 1),
			maxStack:    MaxStack(0, 1),
		},
		PUSH6: &operation{
			execute:     makePush(6, 6),
			constantGas: GasFastestStep,
			minStack:    MinStack(0, 1),
			maxStack:    MaxStack(0, 1),
		},
		PUSH7: &operation{
			execute:     makePush(7, 7),
			constantGas: GasFastestStep,
			minStack:    MinStack(0, 1),
			maxStack:    MaxStack(0, 1),
		},
		PUSH8: &operation{
			execute:     makePush(8, 8),
			constantGas: GasFastestStep,
			minStack:    MinStack(0, 1),
			maxStack:    MaxStack(0, 1),
		},
		PUSH9: &operation{
			execute:     makePush(9, 9),
			constantGas: GasFastestStep,
			minStack:    MinStack(0, 1),
			maxStack:    MaxStack(0, 1),
		},
		PUSH10: &operation{
			execute:     makePush(10, 10),
			constantGas: GasFastestStep,
			minStack:    MinStack(0, 1),
			maxStack:    MaxStack(0, 1),
		},
		PUSH11: &operation{
			execute:     makePush(11, 11),
			constantGas: GasFastestStep,
			minStack:    MinStack(0, 1),
			maxStack:    MaxStack(0, 1),
		},
		PUSH12: &operation{
			execute:     makePush(12, 12),
			constantGas: GasFastestStep,
			minStack:    MinStack(0, 1),
			maxStack:    MaxStack(0, 1),
		},
		PUSH13: &operation{
			execute:     makePush(13, 13),
			constantGas: GasFastestStep,
			minStack:    MinStack(0, 1),
			maxStack:    MaxStack(0, 1),
		},
		PUSH14: &operation{
			execute:     makePush(14, 14),
			constantGas: GasFastestStep,
			minStack:    MinStack(0, 1),
			maxStack:    MaxStack(0, 1),
		},
		PUSH15: &operation{
			execute:     makePush(15, 15),
			constantGas: GasFastestStep,
			minStack:    MinStack(0, 1),
			maxStack:    MaxStack(0, 1),
		},
		PUSH16: &operation{
			execute:     makePush(16, 16),
			constantGas: GasFastestStep,
			minStack:    MinStack(0, 1),
			maxStack:    MaxStack(0, 1),
		},
		PUSH17: &operation{
			execute:     makePush(17, 17),
			constantGas: GasFastestStep,
			minStack:    MinStack(0, 1),
			maxStack:    MaxStack(0, 1),
		},
		PUSH18: &operation{
			execute:     makePush(18, 18),
			constantGas: GasFastestStep,
			minStack:    MinStack(0, 1),
			maxStack:    MaxStack(0, 1),
		},
		PUSH19: &operation{
			execute:     makePush(19, 19),
			constantGas: GasFastestStep,
			minStack:    MinStack(0, 1),
			maxStack:    MaxStack(0, 1),
		},
		PUSH20: &operation{
			execute:     makePush(20, 20),
			constantGas: GasFastestStep,
			minStack:    MinStack(0, 1),
			maxStack:    MaxStack(0, 1),
		},
		PUSH21: &operation{
			execute:     makePush(21, 21),
			constantGas: GasFastestStep,
			minStack:    MinStack(0, 1),
			maxStack:    MaxStack(0, 1),
		},
		PUSH22: &operation{
			execute:     makePush(22, 22),
			constantGas: GasFastestStep,
			minStack:    MinStack(0, 1),
			maxStack:    MaxStack(0, 1),
		},
		PUSH23: &operation{
			execute:     makePush(23, 23),
			constantGas: GasFastestStep,
			minStack:    MinStack(0, 1),
			maxStack:    MaxStack(0, 1),
		},
		PUSH24: &operation{
			execute:     makePush(24, 24),
			constantGas: GasFastestStep,
			minStack:    MinStack(0, 1),
			maxStack:    MaxStack(0, 1),
		},
		PUSH25: &operation{
			execute:     makePush(25, 25),
			constantGas: GasFastestStep,
			minStack:    MinStack(0, 1),
			maxStack:    MaxStack(0, 1),
		},
		PUSH26: &operation{
			execute:     makePush(26, 26),
			constantGas: GasFastestStep,
			minStack:    MinStack(0, 1),
			maxStack:    MaxStack(0, 1),
		},
		PUSH27: &operation{
			execute:     makePush(27, 27),
			constantGas: GasFastestStep,
			minStack:    MinStack(0, 1),
			maxStack:    MaxStack(0, 1),
		},
		PUSH28: &operation{
			execute:     makePush(28, 28),
			constantGas: GasFastestStep,
			minStack:    MinStack(0, 1),
			maxStack:    MaxStack(0, 1),
		},
		PUSH29: &operation{
			execute:     makePush(29, 29),
			constantGas: GasFastestStep,
			minStack:    MinStack(0, 1),
			maxStack:    MaxStack(0, 1),
		},
		PUSH30: &operation{
			execute:     makePush(30, 30),
			constantGas: GasFastestStep,
			minStack:    MinStack(0, 1),
			maxStack:    MaxStack(0, 1),
		},
		PUSH31: &operation{
			execute:     makePush(31, 31),
			constantGas: GasFastestStep,
			minStack:    MinStack(0, 1),
			maxStack:    MaxStack(0, 1),
		},
		PUSH32: &operation{
			execute:     makePush(32, 32),
			constantGas: GasFastestStep,
			minStack:    MinStack(0, 1),
			maxStack:    MaxStack(0, 1),
		},
		DUP1: &operation{
			execute:     makeDup(1),
			constantGas: GasFastestStep,
			minStack:    MinDupStack(1),
			maxStack:    MaxDupStack(1),
		},
		DUP2: &operation{
			execute:     makeDup(2),
			constantGas: GasFastestStep,
			minStack:    MinDupStack(2),
			maxStack:    MaxDupStack(2),
		},
		DUP3: &operation{
			execute:     makeDup(3),
			constantGas: GasFastestStep,
			minStack:    MinDupStack(3),
			maxStack:    MaxDupStack(3),
		},
		DUP4: &operation{
			execute:     makeDup(4),
			constantGas: GasFastestStep,
			minStack:    MinDupStack(4),
			maxStack:    MaxDupStack(4),
		},
		DUP5: &operation{
			execute:     makeDup(5),
			constantGas: GasFastestStep,
			minStack:    MinDupStack(5),
			maxStack:    MaxDupStack(5),
		},
		DUP6: &operation{
			execute:     makeDup(6),
			constantGas: GasFastestStep,
			minStack:    MinDupStack(6),
			maxStack:    MaxDupStack(6),
		},
		DUP7: &operation{
			execute:     makeDup(7),
			constantGas: GasFastestStep,
			minStack:    MinDupStack(7),
			maxStack:    MaxDupStack(7),
		},
		DUP8: &operation{
			execute:     makeDup(8),
			constantGas: GasFastestStep,
			minStack:    MinDupStack(8),
			maxStack:    MaxDupStack(8),
		},
		DUP9: &operation{
			execute:     makeDup(9),
			constantGas: GasFastestStep,
			minStack:    MinDupStack(9),
			maxStack:    MaxDupStack(9),
		},
		DUP10: &operation{
			execute:     makeDup(10),
			constantGas: GasFastestStep,
			minStack:    MinDupStack(10),
			maxStack:    MaxDupStack(10),
		},
		DUP11: &operation{
			execute:     makeDup(11),
			constantGas: GasFastestStep,
			minStack:    MinDupStack(11),
			maxStack:    MaxDupStack(11),
		},
		DUP12: &operation{
			execute:     makeDup(12),
			constantGas: GasFastestStep,
			minStack:    MinDupStack(12),
			maxStack:    MaxDupStack(12),
		},
		DUP13: &operation{
			execute:     makeDup(13),
			constantGas: GasFastestStep,
			minStack:    MinDupStack(13),
			maxStack:    MaxDupStack(13),
		},
		DUP14: &operation{
			execute:     makeDup(14),
			constantGas: GasFastestStep,
			minStack:    MinDupStack(14),
			maxStack:    MaxDupStack(14),
		},
		DUP15: &operation{
			execute:     makeDup(15),
			constantGas: GasFastestStep,
			minStack:    MinDupStack(15),
			maxStack:    MaxDupStack(15),
		},
		DUP16: &operation{
			execute:     makeDup(16),
			constantGas: GasFastestStep,
			minStack:    MinDupStack(16),
			maxStack:    MaxDupStack(16),
		},
		SWAP1: &operation{
			execute:     makeSwap(1),
			constantGas: GasFastestStep,
			minStack:    MinSwapStack(2),
			maxStack:    MaxSwapStack(2),
		},
		SWAP2: &operation{
			execute:     makeSwap(2),
			constantGas: GasFastestStep,
			minStack:    MinSwapStack(3),
			maxStack:    MaxSwapStack(3),
		},
		SWAP3: &operation{
			execute:     makeSwap(3),
			constantGas: GasFastestStep,
			minStack:    MinSwapStack(4),
			maxStack:    MaxSwapStack(4),
		},
		SWAP4: &operation{
			execute:     makeSwap(4),
			constantGas: GasFastestStep,
			minStack:    MinSwapStack(5),
			maxStack:    MaxSwapStack(5),
		},
		SWAP5: &operation{
			execute:     makeSwap(5),
			constantGas: GasFastestStep,
			minStack:    MinSwapStack(6),
			maxStack:    MaxSwapStack(6),
		},
		SWAP6: &operation{
			execute:     makeSwap(6),
			constantGas: GasFastestStep,
			minStack:    MinSwapStack(7),
			maxStack:    MaxSwapStack(7),
		},
		SWAP7: &operation{
			execute:     makeSwap(7),
			constantGas: GasFastestStep,
			minStack:    MinSwapStack(8),
			maxStack:    MaxSwapStack(8),
		},
		SWAP8: &operation{
			execute:     makeSwap(8),
			constantGas: GasFastestStep,
			minStack:    MinSwapStack(9),
			maxStack:    MaxSwapStack(9),
		},
		SWAP9: &operation{
			execute:     makeSwap(9),
			constantGas: GasFastestStep,
			minStack:    MinSwapStack(10),
			maxStack:    MaxSwapStack(10),
		},
		SWAP10: &operation{
			execute:     makeSwap(10),
			constantGas: GasFastestStep,
			minStack:    MinSwapStack(11),
			maxStack:    MaxSwapStack(11),
		},
		SWAP11: &operation{
			execute:     makeSwap(11),
			constantGas: GasFastestStep,
			minStack:    MinSwapStack(12),
			maxStack:    MaxSwapStack(12),
		},
		SWAP12: &operation{
			execute:     makeSwap(12),
			constantGas: GasFastestStep,
			minStack:    MinSwapStack(13),
			maxStack:    MaxSwapStack(13),
		},
		SWAP13: &operation{
			execute:     makeSwap(13),
			constantGas: GasFastestStep,
			minStack:    MinSwapStack(14),
			maxStack:    MaxSwapStack(14),
		},
		SWAP14: &operation{
			execute:     makeSwap(14),
			constantGas: GasFastestStep,
			minStack:    MinSwapStack(15),
			maxStack:    MaxSwapStack(15),
		},
		SWAP15: &operation{
			execute:     makeSwap(15),
			constantGas: GasFastestStep,
			minStack:    MinSwapStack(16),
			maxStack:    MaxSwapStack(16),
		},
		SWAP16: &operation{
			execute:     makeSwap(1),
			constantGas: GasFastestStep,
			minStack:    MinSwapStack(17),
			maxStack:    MaxSwapStack(17),
		},
		LOG0: &operation{
			execute:    makeLog(0),
			dynamicGas: makeGasLog(0),
			minStack:   MinStack(2, 0),
			maxStack:   MaxStack(2, 0),
			memorySize: MemoryLog,
		},
		LOG1: &operation{
			execute:    makeLog(1),
			dynamicGas: makeGasLog(1),
			minStack:   MinStack(3, 0),
			maxStack:   MaxStack(3, 0),
			memorySize: MemoryLog,
		},
		LOG2: &operation{
			execute:    makeLog(2),
			dynamicGas: makeGasLog(2),
			minStack:   MinStack(4, 0),
			maxStack:   MaxStack(4, 0),
			memorySize: MemoryLog,
		},
		LOG3: &operation{
			execute:    makeLog(3),
			dynamicGas: makeGasLog(3),
			minStack:   MinStack(5, 0),
			maxStack:   MaxStack(5, 0),
			memorySize: MemoryLog,
		},
		LOG4: &operation{
			execute:    makeLog(4),
			dynamicGas: makeGasLog(4),
			minStack:   MinStack(6, 0),
			maxStack:   MaxStack(6, 0),
			memorySize: MemoryLog,
		},
		CREATE: &operation{
			execute:     opCreate,
			constantGas: params.CreateGas,
			dynamicGas:  gasCreate,
			minStack:    MinStack(3, 1),
			maxStack:    MaxStack(3, 1),
		},
		CALL: &operation{
			execute:     opCall,
			constantGas: params.CallGasFrontier,
			// dynamicGas:  gasCall,
			minStack:   MinStack(7, 1),
			maxStack:   MaxStack(7, 1),
			memorySize: MemoryCall,
		},
		CALLCODE: &operation{
			execute:     opCallCode,
			constantGas: params.CallGasFrontier,
			// dynamicGas: gasCallCode,
			minStack:   MinStack(7, 1),
			maxStack:   MaxStack(7, 1),
			memorySize: MemoryCall,
		},
		RETURN: &operation{
			execute:    opReturn,
			dynamicGas: gasReturn,
			minStack:   MinStack(2, 0),
			maxStack:   MaxStack(2, 0),
			memorySize: MemoryReturn,
			returns:    true,
			finished:   true,
		},
		SELFDESTRUCT: &operation{
			execute: opSelfdestruct,
			// dynamicGas: gasSelfdestruct,
			minStack: MinStack(1, 0),
			maxStack: MaxStack(1, 0),
			returns:  true,
			finished: true,
		},
	}

	for i, entry := range table {
		if entry == nil {
			table[i] = &operation{execute: opUndefined, maxStack: MaxStack(0, 0)}
		}
	}

	return table
}
